<template>
  <el-dialog v-model="dialogVisible" :close-on-click-modal="closeOnClickModal" :width="width">
    <div class="dialog-container">
      <div class="left-card">
        <img alt="登录注册图片" src="@/assets/login.png" />
      </div>
      <div class="right-tabs">
        <div class="right-side-title-wrapper">
          <el-text class="login-title" type="primary">Welcome Melody Flow</el-text>
          <el-text class="login-sub-title" type="info">
            "Melody Flow，音乐爱好者的聚集地，让我们一起为音符赋予生命。"
          </el-text>
        </div>
        <el-tabs v-model="activeTab" stretch>
          <el-tab-pane label="登录" name="login">
            <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" @keyup.enter="handleLoginSubmit">
              <el-form-item prop="username">
                <el-input v-model="loginForm.username" :prefix-icon="User" placeholder="用户名/邮箱" />
              </el-form-item>
              <el-form-item prop="password">
                <el-input
                  v-model="loginForm.password"
                  :prefix-icon="Lock"
                  placeholder="密码"
                  show-password
                  type="password"
                />
              </el-form-item>
              <el-form-item prop="captchaCode">
                <div class="captcha-container">
                  <el-input
                    v-model="loginForm.captchaCode"
                    :prefix-icon="Picture"
                    class="captcha-input"
                    placeholder="请输入验证码"
                  />
                  <img :src="captchaImg" alt="图片验证码" class="captcha-image" @click="refreshCaptcha" />
                </div>
              </el-form-item>
              <div class="dialog-footer">
                <el-button :loading="isLoading.login" type="primary" @click="handleLoginSubmit"> 立即登录</el-button>
                <el-button link type="primary" @click="handleForgetPassword"> 忘记密码？</el-button>
              </div>
            </el-form>
          </el-tab-pane>

          <el-tab-pane label="注册" name="register">
            <el-form ref="registerFormRef" :model="registerForm" :rules="registerRules">
              <el-form-item prop="email">
                <div class="email-verify-container">
                  <el-input v-model="registerForm.email" :prefix-icon="Message" placeholder="邮箱" />
                  <el-button :disabled="isSending || !registerForm.email" @click="handleSendEmail">
                    {{ countdown > 0 ? `${countdown}秒后重试` : '发送验证码' }}
                  </el-button>
                </div>
              </el-form-item>
              <el-form-item prop="code">
                <el-input v-model="registerForm.code" :prefix-icon="Key" placeholder="请输入邮箱验证码" />
              </el-form-item>
              <el-form-item prop="password">
                <el-input
                  v-model="registerForm.password"
                  :prefix-icon="Lock"
                  placeholder="至少8位以上且包含字母、数字、特殊符号"
                  show-password
                  type="password"
                />
              </el-form-item>
              <el-form-item prop="repeatPass">
                <el-input
                  v-model="registerForm.repeatPass"
                  :prefix-icon="Lock"
                  placeholder="确认密码"
                  show-password
                  type="password"
                />
              </el-form-item>
              <el-button :loading="isLoading.register" class="w-full" type="primary" @click="handleRegisterSubmit">
                立即注册
              </el-button>
            </el-form>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
  </el-dialog>
</template>

<script setup>
import { defineEmits, defineProps, reactive, ref, watch } from 'vue'
import { Key, Lock, Message, Picture, User } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { oAuthEmail, oAuthKaptCha, oAuthLogin, oAuthRegister } from '@/api/oAuth.js'

const props = defineProps({
  modelValue: Boolean,
  width: { type: [String, Number], default: '900px' },
  closeOnClickModal: { type: Boolean, default: false }
})

const emit = defineEmits(['update:modelValue', 'login-success', 'register-success'])

const dialogVisible = ref(false)
const activeTab = ref('login')

const loginForm = reactive({ username: '', password: '', kaptchaKey: '', captchaCode: '' })
const loginFormRef = ref()
const loginRules = {
  username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 8, max: 20, message: '长度在8-20个字符', trigger: 'blur' }
  ],
  captchaCode: [
    { required: true, message: '请输入验证码', trigger: 'blur' },
    { len: 5, message: '验证码为5位字符', trigger: 'blur' }
  ]
}

const captchaImg = ref('')

const registerForm = reactive({
  email: '',
  password: '',
  repeatPass: '',
  code: ''
})
const registerFormRef = ref()
const registerRules = {
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { type: 'email', message: '邮箱格式不正确' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    {
      validator: (_, v, cb) =>
        /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*.])[\da-zA-Z~!@#$%^&*.]{8,}$/.test(v)
          ? cb()
          : cb(new Error('密码需8位以上且包含字母、数字、特殊符号'))
    }
  ],
  repeatPass: [{ validator: (_, v, cb) => (v === registerForm.password ? cb() : cb(new Error('密码不一致'))) }],
  code: [
    { required: true, message: '请输入邮箱验证码', trigger: 'blur' },
    { len: 6, message: '验证码为6位字母或数字', trigger: 'blur' }
  ]
}

const countdown = ref(0)
const isSending = ref(false)
const isLoading = reactive({
  login: false,
  register: false,
  captchaLoading: false
})

watch(
  () => props.modelValue,
  val => {
    dialogVisible.value = val
    clearInfo()
  }
)
watch(dialogVisible, val => {
  emit('update:modelValue', val)
  if (val) refreshCaptcha()
})
watch(activeTab, val => {
  clearInfo()
})

const refreshCaptcha = async () => {
  try {
    const response = await oAuthKaptCha()
    captchaImg.value = response.data.img
    loginForm.kaptchaKey = response.data.key
  } catch (error) {
    console.log(error)
  }
}

const handleSendEmail = async () => {
  let timer = null
  try {
    await registerFormRef.value.validateField('email')
    isSending.value = true
    const response = await oAuthEmail(registerForm.email)
    countdown.value = 60
    timer = setInterval(() => {
      countdown.value--
      if (countdown.value <= 0) {
        clearInterval(timer)
        isSending.value = false
      }
    }, 1000)
    ElMessage.success('验证码已发送至邮箱')
  } catch (error) {
    console.log(error)
    isSending.value = false
    countdown.value = 0
    if (timer) clearInterval(timer)
  }
}

const handleLoginSubmit = async () => {
  try {
    await loginFormRef.value.validate()
    isLoading.login = true
    const response = await oAuthLogin({
      ...loginForm
    })
    emit('login-success', response)
    dialogVisible.value = false
  } catch (error) {
    await refreshCaptcha()
  } finally {
    isLoading.login = false
  }
}

const handleRegisterSubmit = async () => {
  try {
    await registerFormRef.value.validate()
    isLoading.register = true
    const response = await oAuthRegister({
      ...registerForm
    })
    emit('register-success', response)
    activeTab.value = 'login'
  } catch (error) {
    console.error(error)
  } finally {
    isLoading.register = false
  }
}

const handleForgetPassword = () => {
  ElMessage.info('请查看注册邮箱或联系管理员')
}

const clearInfo = () => {
  Object.keys(loginForm).forEach(key => {
    loginForm[key] = ''
  })
  loginFormRef.value?.clearValidate()
  Object.keys(registerForm).forEach(key => {
    registerForm[key] = ''
  })
  registerFormRef.value?.clearValidate()
  countdown.value = 0
}
</script>

<style scoped>
.dialog-footer {
  display: flex;
  justify-content: space-between;
  margin-top: 20px;
}

.el-form-item {
  margin-bottom: 22px;
}

.w-full {
  width: 100%;
}

.captcha-container {
  display: flex;
  gap: 10px;
  width: 100%;
}

.captcha-input {
  flex: 1;
}

.captcha-image {
  height: 40px;
  cursor: pointer;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
}

.email-verify-container {
  display: flex;
  gap: 10px;
}

.email-verify-container .el-input {
  flex: 1;
}

.email-verify-container .el-button {
  width: 120px;
  flex-shrink: 0;
}

:deep(.el-tabs__nav-wrap:after),
:deep(.el-tabs__active-bar) {
  height: 0;
}

:deep(.el-tabs__item) {
  font-weight: bold;
}

.dialog-container {
  display: flex;
  gap: 20px;
  height: 450px;
}

.left-card {
  flex: 6;
  width: 60%;
  max-width: 60%;
  display: flex;
  align-items: center;
  background: #f5f7fa;
  border-radius: 8px;
  overflow: hidden;
}

.left-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.right-tabs {
  flex: 4;
  width: 40%;
  padding: 20px 30px;
  overflow: auto;
}

.right-side-title-wrapper {
  margin-bottom: 10px;
  text-align: center;
}

.login-title {
  font-size: 27px;
  font-weight: 600;
  line-height: 1.5;
  display: block;
  margin-bottom: 5px;
}

.login-sub-title {
  font-size: 12px;
  color: var(--el-text-color-secondary);
  display: inline-block;
}
</style>
